package com.yx.changdao.web.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.yx.changdao.common.annotation.AutoLog;
import com.yx.changdao.common.annotation.ShiroDesc;
import com.yx.changdao.common.data.Pager;
import com.yx.changdao.common.data.Result;
import com.yx.changdao.common.entity.*;
import com.yx.changdao.common.enums.problem.Report;
import com.yx.changdao.common.enums.problem.ReportManager;
import com.yx.changdao.common.exception.AlertException;
import com.yx.changdao.common.utils.*;
import com.yx.changdao.common.valid.Default;
import com.yx.changdao.common.valid.Update;
import com.yx.changdao.common.vo.ProblemInfoVo;
import com.yx.changdao.common.vo.ProblemVo;
import com.yx.changdao.service.*;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.hibernate.validator.constraints.Range;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.ResourceUtils;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 问题录入模块
 *
 * @Auther: wangzd
 * @create 2020/04/03 16:51
 */
@RestController
@RequestMapping("/problem/input")
public class ProblemInputController {

    /**
     * 问题信息(在分配之前)服务
     */
    @Autowired
    private ProblemInfoService problemInfoService;

    @Autowired
    private ProblemService problemService;
    @Autowired
    private CommunityBuildService communityBuildService;
    @Autowired
    private CommunityBuildDetailService communityBuildDetailService;
    @Autowired
    private GridInfoService gridInfoService;

    /**
     * 列表
     */
    @AutoLog
    @GetMapping("/list")
    @RequiresPermissions("problem:input:list")
    @ShiroDesc("问题录入:列表")
    public Result list(@RequestParam(value = "page") Long page,
                       @RequestParam(value = "limit", required = false) Integer limit) throws AlertException {

        if (limit == null) {
            limit = SysConst.LIMIT_PAGE;
        }
        // 分页配置
        Page<ProblemInfo> pager = new Page<>(page, limit);
        // 根据请求解析条件。
        QueryWrapper<ProblemInfo> qw = SysUtils.autoCnd(ProblemInfo.class);

        qw.orderByDesc(ProblemInfo.CREATE_TIME); //时间倒序

        qw.eq(ProblemInfo.CREATE_BY, SysUtils.currentUserId()); //创建人为当前登陆人

        // 获取分页结果集。
        Page<ProblemInfo> infoPage = problemInfoService.page(pager, qw);

        int inputNum = problemInfoService.count(new QueryWrapper<ProblemInfo>()  //录入问题数量
                .eq(ProblemInfo.CREATE_BY, SysUtils.currentUserId()));

        int reportNum = problemInfoService.count(new QueryWrapper<ProblemInfo>()  //上报问题数量
                .eq(ProblemInfo.CREATE_BY, SysUtils.currentUserId())
                .in(ProblemInfo.IF_REPORT, 2, 1)); //上报通过的,上报审核的

        List<ProblemInfoVo> collect = infoPage.getRecords().stream().map(t -> {
            ProblemInfoVo vo = new ProblemInfoVo();
            BeanUtils.copyProperties(t, vo);
            GridInfo gridInfo = gridInfoService.getById(vo.getGridId());
            if (null != gridInfo) {
                vo.setGridId(Integer.valueOf(gridInfo.getGridNum()));
            }
            vo.setReport(Report.info(vo.getIfReport()).n());
            vo.setReportManager(ReportManager.info(vo.getIfReportManager()).n());
            vo.setResidentIdcard(DesensitizationUtils.idEncrypt(vo.getResidentIdcard()));
            return vo;
        }).collect(Collectors.toList());


        Map<String, Object> map = new HashMap<>();
        map.put("list", collect);
        map.put("pager", new Pager(infoPage));

        HashMap<String, Integer> num = new HashMap<>(); //录入问题数量 和上报问题数量
        num.put("input", inputNum);
        num.put("report", reportNum);
        map.put("nums", num);

        return Result.ok().data(map);
    }

    /**
     * 录入问题
     */
    @AutoLog
    @PostMapping
    /*@RequiresPermissions("problem:input:add")
    @ShiroDesc("问题录入:添加")*/
    public Result add(@RequestBody @Validated(Default.class) ProblemInfo problemInfo) throws AlertException {

        problemInfo.setProblemInfoId(null);

        boolean b = problemInfoService.saveOrUpdateProblem(problemInfo, true);
        if (!b) {
            throw new AlertException("问题添加失败");
        }
        return Result.ok("问题添加成功");
    }

    /**
     * 更新问题
     *
     * @param
     * @return Result
     */
    @AutoLog
    @PutMapping
    /*@RequiresPermissions("problem:input:save")
    @ShiroDesc("问题录入:保存")*/
    public Result update(@RequestBody @Validated(Update.class) ProblemInfo ProblemInfo) throws AlertException {

        ProblemInfo problemInfo = problemInfoService.getById(ProblemInfo.getProblemInfoId());

        if (problemInfo.getIfReportManager().equals(1)) {
            throw new AlertException("问题已经上报管理员无法修改");
        }

        if (problemInfo.getIfReport().equals(1) || problemInfo.getIfReport().equals(2)) {
            throw new AlertException("问题已经上报无法修改");
        }

        boolean b = problemInfoService.saveOrUpdateProblem(ProblemInfo, true);
        if (!b) {
            throw new AlertException("问题更新失败");
        }
        return Result.ok("问题更新成功");
    }


    /**
     * 删除问题
     *
     * @param
     * @return Result
     */
    @AutoLog
    @DeleteMapping("/{id}")
    /*@RequiresPermissions("problem:input:del")
    @ShiroDesc("问题录入:删除")*/
    public Result delete(@PathVariable("id") Integer id) throws AlertException {

        problemInfoService.deleteProblem(id);

        return Result.ok("删除问题成功");
    }


    /**
     * 问题模板下载
     */
    @AutoLog
    @GetMapping("/template")
    // @RequiresPermissions("problem:template")
    // @ShiroDesc("问题:模板")
    public void template(HttpServletResponse response) throws Exception {

        File cfgFile = ResourceUtils.getFile("classpath:public/意见建议统一表头.xlsx");
        Faster.download(response, cfgFile);
    }

    /**
     * 批量添加问题
     */
    @AutoLog
    @PostMapping("/batch")
   /* @RequiresPermissions("problem:input:add:batch")
    @ShiroDesc("问题录入:批量添加")*/
    public Result batchAdd(@RequestParam("problem") MultipartFile problem) throws AlertException {

        /**
         * 保存没有正常问题, 返回异常问题
         */
        List<ProblemInfo> problemInfos = problemInfoService.checkAndSave(problem);
        return Result.ok("导入成功");
    }

    /**
     * 上报 (普通账户上报管理员)
     */
    @AutoLog
    @PutMapping("/report/manager")
    public Result reportManager(@RequestParam("problemInfoId") Integer problemInfoId) throws AlertException {

        if (!problemInfoService.reportManager(problemInfoId)) {
            throw new AlertException("问题上报管理员成功失败");
        }
        return Result.ok("问题上报管理员成功");
    }

    /**
     * 批量上报 (普通账户上报管理员)
     */
    @AutoLog
    @PutMapping("/batch/report/manager")
    public Result batchReportManager(@RequestParam("problemInfoIds") String problemInfoIds) throws AlertException {

        if (!problemInfoService.reportBatchManager(Faster.batch2(problemInfoIds))) {
            throw new AlertException("问题上报管理员成功失败");
        }
        return Result.ok("问题上报管理员成功");
    }


    //管理员-------------------------------------------------------------------------------------------------------------------------------------------

    /**
     * 管理员驳回上报
     */
    @AutoLog
    @PutMapping("/report/reject")
    public Result reject(@RequestParam("problemInfoId") Integer id) throws AlertException {

        if (!problemInfoService.rejectManager(id)) {
            throw new AlertException("操作失败");
        }
        return Result.ok("操作成功");
    }


    /**
     * 管理员更新问题
     *
     * @param
     * @return Result
     */
    @AutoLog
    @PutMapping("/manager")
    public Result updateManager(@RequestBody @Validated(Update.class) ProblemInfo ProblemInfo) throws AlertException {

        ProblemInfo problemInfo = problemInfoService.getById(ProblemInfo.getProblemInfoId());

        if (problemInfo.getIfReport().equals(1) || problemInfo.getIfReport().equals(2)) {
            throw new AlertException("问题已经上报无法修改");
        }
        boolean b = problemInfoService.saveOrUpdateProblem(ProblemInfo, true);
        if (!b) {
            throw new AlertException("问题更新失败");
        }
        return Result.ok("问题更新成功");
    }

    /**
     * 管理员上报列表
     */
    @AutoLog
    @GetMapping("/report/list")
    @RequiresPermissions("problem:input:report:list")
    @ShiroDesc("问题录入上报:列表")
    public Result listReport(@RequestParam(value = "page") Long page,
                             @RequestParam(value = "limit", required = false) Integer limit) {

        if (limit == null) {
            limit = SysConst.LIMIT_PAGE;
        }
        // 分页配置
        Page<ProblemInfo> pager = new Page<>(page, limit);
        // 根据请求解析条件。
        QueryWrapper<ProblemInfo> qw = SysUtils.autoCnd(ProblemInfo.class);

        qw.orderByDesc(ProblemInfo.CREATE_TIME); //时间倒序

        qw.eq(ProblemInfo.REPORT_DEP_ID, SysUtils.currentUser().getDepId()); //当前部门录入的
        qw.eq(ProblemInfo.IF_REPORT_MANAGER, 1); //上报给管理员的 待继续上报的

        // 获取分页结果集。
        Page<ProblemInfo> infoPage = problemInfoService.page(pager, qw);

        int inputNum = problemInfoService.count(new QueryWrapper<ProblemInfo>()  //录入问题数量
                .eq(ProblemInfo.REPORT_DEP_ID, SysUtils.currentUser().getDepId()));

        int reportNum = problemInfoService.count(new QueryWrapper<ProblemInfo>()  //上报问题数量
                .eq(ProblemInfo.REPORT_DEP_ID, SysUtils.currentUser().getDepId())
                .in(ProblemInfo.IF_REPORT, 2, 1)); //上报通过的,上报审核的

        List<ProblemInfoVo> collect = infoPage.getRecords().stream().map(t -> {
            ProblemInfoVo vo = new ProblemInfoVo();
            BeanUtils.copyProperties(t, vo);
            GridInfo gridInfo = gridInfoService.getById(vo.getGridId());
            if (null != gridInfo) {
                vo.setGridId(Integer.valueOf(gridInfo.getGridNum()));
            }
            vo.setReport(Report.info(vo.getIfReport()).n());
            vo.setReportManager(ReportManager.info(vo.getIfReportManager()).n());
            vo.setResidentIdcard(DesensitizationUtils.idEncrypt(vo.getResidentIdcard()));
            return vo;
        }).collect(Collectors.toList());

        Map<String, Object> map = new HashMap<>();
        map.put("list", collect);
        map.put("pager", new Pager(infoPage));

        HashMap<String, Integer> num = new HashMap<>(); //录入问题数量 和上报问题数量
        num.put("input", inputNum);
        num.put("report", reportNum);
        map.put("nums", num);

        return Result.ok().data(map);
    }

    /**
     *
     */
    @AutoLog
    @GetMapping("/export")
    public void export(@RequestParam("ids") String ids) throws Exception {

        QueryWrapper<ProblemInfo> qw = SysUtils.autoCnd(ProblemInfo.class);
        List<Integer> idsList = Faster.batch2(ids);
        if (!idsList.isEmpty()) {
            qw.in(ProblemInfo.PROBLEM_INFO_ID, idsList);
        }

        List<ProblemInfo> list = problemInfoService.list(qw);

        List<String> cloudms = new ArrayList<>();
        cloudms.add("residentName:反馈居民姓名");

        cloudms.add("gridId:网格id");
        cloudms.add("buildCode:楼编号");
        cloudms.add("buildName:楼名称");
        cloudms.add("unit:单元号");
        cloudms.add("doorPlate:室号");

        cloudms.add("residentPhone:反馈居民手机号");
        cloudms.add("residentAddress:反馈居民地址");

        cloudms.add("residentIdcard:反馈居民身份证号");

        cloudms.add("category:意见建议类别");
        cloudms.add("industryCategory:意见建议行业类别");
        cloudms.add("content:意见建议内容");
        cloudms.add("difficultLevel:办理难度");

        cloudms.add("contact1Name:联户人1姓名");
        cloudms.add("contact1Phone:联户人1手机号");
        cloudms.add("contact2Name:联户人2手机号");
        cloudms.add("contact2Phone:联户人2手机号");


        ExcelImportExportUtils.writeExcelByCloum(list, SysUtils.getResponse(), "导出", cloudms);
    }


    /**
     * 问题上报 (管理员上报给执行)
     */
    @AutoLog
    @PutMapping("/report")
    public Result report(@RequestParam("problemInfoId") Integer problemInfoId) throws AlertException {
        boolean b = problemInfoService.report(problemInfoId);
        if (!b) {
            throw new AlertException("问题已上报");
        }
        return Result.ok("问题上报成功");
    }

    /**
     * 问题批量上报 (管理员上报给执行)
     */
    @AutoLog
    @PutMapping("/batch/report")
    public Result batchReport(@RequestParam("problemInfoIds") String problemInfoIds) throws AlertException {
        boolean b = problemInfoService.reportBatch(Faster.batch2(problemInfoIds));
        if (!b) {
            throw new AlertException("问题已上报");
        }
        return Result.ok("问题上报成功");
    }

    public static void main(String[] args) {
        QueryWrapper<CommunityBuild> buildName = new QueryWrapper<CommunityBuild>()
                .like(CommunityBuild.BUILD_NAME, "buildName")
                .eq(CommunityBuild.DEP_ID, SysUtils.currentUser().getDepId());

        System.out.println(buildName.getSqlSelect());
    }

    /**
     * 部门联户人小组服务
     */
    @Autowired
    private DepContactGroupService depContactGroupService;


    /**
     * 查询楼信息
     */
    @AutoLog
    @GetMapping("/build")
    public Result getDepBuildByBuildName(String buildName) {

        DepContactGroup group =
                depContactGroupService.getById(SysUtils.currentUser().getContactGroupId());

        if (Faster.isNull(group)) {
            return Result.ok("无小组");
        }

        List<Integer> collect = communityBuildDetailService.
                list(new QueryWrapper<CommunityBuildDetail>()
                        .eq(CommunityBuildDetail.CONTACT_GROUP_ID, group.getContactGroupId()))

                .stream().map(t -> t.getBuildId()).collect(Collectors.toList());

        if (Faster.IsEmpty(collect)) {
            return Result.ok("无建筑");
        }

        QueryWrapper<CommunityBuild> wrapper = new QueryWrapper<CommunityBuild>()
                .in(CommunityBuild.ID, collect);

        if (StringUtils.isNotBlank(buildName)) {
            wrapper.like(CommunityBuild.BUILD_NAME, buildName);
        }

        List<CommunityBuild> list = communityBuildService.list(wrapper);

        ArrayList<Map<String, String>> maps = new ArrayList<>();
        for (CommunityBuild communityBuild : list) {
            HashMap<String, String> map = new HashMap<>();
            map.put("buildId", communityBuild.getId() + "");
            map.put("buildCode", communityBuild.getBuildCode());
            map.put("value", communityBuild.getBuildName());
            maps.add(map);
        }
        return Result.ok().data(maps);
    }

    /**
     * 查询单元
     */
    @AutoLog
    @GetMapping("/build/unit")
    public Result getDepUnit(@RequestParam("buildId") String buildId) {
        List<CommunityBuildDetail> list = communityBuildDetailService.list(new QueryWrapper<CommunityBuildDetail>()
                .eq(CommunityBuildDetail.BUILD_ID, buildId).groupBy(CommunityBuildDetail.UNIT));

        ArrayList<Map<String, String>> maps = new ArrayList<>();
        for (CommunityBuildDetail communityBuildDetail : list) {
            HashMap<String, String> map = new HashMap<>();
            map.put("unit", communityBuildDetail.getUnit() + "");
            maps.add(map);
        }
        return Result.ok().data(maps);
    }

    /**
     * 查询房间
     */
    @AutoLog
    @GetMapping("/build/doorplate")
    public Result getDepDoorplate(@RequestParam("buildId") String buildId,
                                  @RequestParam("unit") String unit) {
        List<CommunityBuildDetail> list = communityBuildDetailService.list(new QueryWrapper<CommunityBuildDetail>()
                .eq(CommunityBuildDetail.BUILD_ID, buildId)
                .eq(CommunityBuildDetail.UNIT, unit));

        ArrayList<Map<String, String>> maps = new ArrayList<>();
        for (CommunityBuildDetail communityBuildDetail : list) {
            HashMap<String, String> map = new HashMap<>();
            map.put("doorPlate", communityBuildDetail.getDoorPlate());
            maps.add(map);
        }
        return Result.ok().data(maps);
    }

}
